using System;
using System.Collections.Generic;

using SBPweb.Common.Caching;
using SBPweb.Common.Session;

using SBPweb.PROvibe.Resources.Warehouse.ActorSiteRole;

using SBPweb.PROvibe.Business.Logic;

namespace SBPweb.PROvibe.Business.Warehouse
{
	public class ActorSiteRoleFactory
	{

		#region Private static string constants

		private static string CACHEKEY_ACTORSITEROLES = "Warehouse.ActorSiteRoles";
		private static string CACHEKEY_ACTORSITEROLES_INDEX_ACTORID = "Warehouse.ActorSiteRoles.Index.ActorId";
		private static string CACHEKEY_ACTORSITEROLES_INDEX_SITEID = "Warehouse.ActorSiteRoles.Index.SiteId";
		private static string CACHEKEY_ACTORSITEROLES_INDEX_ROLEID = "Warehouse.ActorSiteRoles.Index.RoleId";

		private static string SESSIONKEY_ACTORSITEROLES = "_Repository.ActorSiteRoles";

		#endregion

		#region Private fields

		private static ActorSiteRoleRepository mActorSiteRoleRepository
		{
			get
			{
				ActorSiteRoleRepository ret = SessionHandler.Get<ActorSiteRoleRepository>(SESSIONKEY_ACTORSITEROLES);

				if (ret == null)
				{
					ret = new ActorSiteRoleRepository(ConfigurationManager.ConnectionStrings.Warehouse);
					SessionHandler.Put<ActorSiteRoleRepository>(SESSIONKEY_ACTORSITEROLES, ret);
				}

				return ret;
			}
		}

		private static Dictionary<int, List<Entities.ActorSiteRole>> mActorSiteRoleListByActorId
		{
			get
			{
				bool isCached = ConfigurationManager.CacheExpirations.IsCachingUsed;

				Dictionary<int, List<Entities.ActorSiteRole>> actorSiteRolesIdx;
				if (isCached && CacheHandler.GetAccessLogClone().ContainsKey(CACHEKEY_ACTORSITEROLES_INDEX_ACTORID))
				{
					actorSiteRolesIdx = CacheHandler.Retrieve<Dictionary<int, List<Entities.ActorSiteRole>>>(CACHEKEY_ACTORSITEROLES_INDEX_ACTORID);
				}
				else
				{
					List<Entities.ActorSiteRole> actorsSiteRoles = ConvertResourcesEntityList(mActorSiteRoleRepository.GetActorSiteRoles());
					actorSiteRolesIdx = new Dictionary<int, List<Entities.ActorSiteRole>>();
					foreach (Entities.ActorSiteRole asr in actorsSiteRoles)
					{
						if (!actorSiteRolesIdx.ContainsKey(asr.ActorId))
						{
							actorSiteRolesIdx.Add(asr.ActorId, new List<Entities.ActorSiteRole>());
						}
						actorSiteRolesIdx[asr.ActorId].Add(asr);
					}
					if (isCached)
					{
						CacheHandler.Store<Dictionary<int, List<Entities.ActorSiteRole>>>(CACHEKEY_ACTORSITEROLES_INDEX_ACTORID, actorSiteRolesIdx, ConfigurationManager.CacheExpirations.Warehouse.ActorSiteRoles);
					}
				}
				return actorSiteRolesIdx;
			}
		}

		private static Dictionary<int, List<Entities.ActorSiteRole>> mActorSiteRoleListBySiteId
		{
			get
			{
				bool isCached = ConfigurationManager.CacheExpirations.IsCachingUsed;

				Dictionary<int, List<Entities.ActorSiteRole>> actorSiteRolesIdx;
				if (isCached && CacheHandler.GetAccessLogClone().ContainsKey(CACHEKEY_ACTORSITEROLES_INDEX_SITEID))
				{
					actorSiteRolesIdx = CacheHandler.Retrieve<Dictionary<int, List<Entities.ActorSiteRole>>>(CACHEKEY_ACTORSITEROLES_INDEX_SITEID);
				}
				else
				{
					List<Entities.ActorSiteRole> actorsSiteRoles = ConvertResourcesEntityList(mActorSiteRoleRepository.GetActorSiteRoles());
					actorSiteRolesIdx = new Dictionary<int, List<Entities.ActorSiteRole>>();
					foreach (Entities.ActorSiteRole asr in actorsSiteRoles)
					{
						if (!actorSiteRolesIdx.ContainsKey(asr.SiteId))
						{
							actorSiteRolesIdx.Add(asr.SiteId, new List<Entities.ActorSiteRole>());
						}
						actorSiteRolesIdx[asr.SiteId].Add(asr);
					}
					if (isCached)
					{
						CacheHandler.Store<Dictionary<int, List<Entities.ActorSiteRole>>>(CACHEKEY_ACTORSITEROLES_INDEX_SITEID, actorSiteRolesIdx, ConfigurationManager.CacheExpirations.Warehouse.ActorSiteRoles);
					}
				}
				return actorSiteRolesIdx;
			}
		}

		private static Dictionary<int, List<Entities.ActorSiteRole>> mActorSiteRoleListByRoleId
		{
			get
			{
				bool isCached = ConfigurationManager.CacheExpirations.IsCachingUsed;

				Dictionary<int, List<Entities.ActorSiteRole>> actorSiteRolesIdx;
				if (isCached && CacheHandler.GetAccessLogClone().ContainsKey(CACHEKEY_ACTORSITEROLES_INDEX_ROLEID))
				{
					actorSiteRolesIdx = CacheHandler.Retrieve<Dictionary<int, List<Entities.ActorSiteRole>>>(CACHEKEY_ACTORSITEROLES_INDEX_ROLEID);
				}
				else
				{
					List<Entities.ActorSiteRole> actorsSiteRoles = ConvertResourcesEntityList(mActorSiteRoleRepository.GetActorSiteRoles());
					actorSiteRolesIdx = new Dictionary<int, List<Entities.ActorSiteRole>>();
					foreach (Entities.ActorSiteRole asr in actorsSiteRoles)
					{
						if (!actorSiteRolesIdx.ContainsKey(asr.RoleId))
						{
							actorSiteRolesIdx.Add(asr.RoleId, actorSiteRolesIdx[asr.RoleId] = new List<Entities.ActorSiteRole>());
						}
						actorSiteRolesIdx[asr.RoleId].Add(asr);
					}
					if (isCached)
					{
						CacheHandler.Store<Dictionary<int, List<Entities.ActorSiteRole>>>(CACHEKEY_ACTORSITEROLES_INDEX_ROLEID, actorSiteRolesIdx, ConfigurationManager.CacheExpirations.Warehouse.ActorSiteRoles);
					}
				}
				return actorSiteRolesIdx;
			}
		}

		private static List<Entities.ActorSiteRole> mActorSiteRoles
		{
			get
			{
				bool isCached = ConfigurationManager.CacheExpirations.IsCachingUsed;

				if (isCached && CacheHandler.GetAccessLogClone().ContainsKey(CACHEKEY_ACTORSITEROLES))
				{
					return CacheHandler.Retrieve<List<Entities.ActorSiteRole>>(CACHEKEY_ACTORSITEROLES);
				}
				else
				{
					List<Entities.ActorSiteRole> actorsSiteRoles = ConvertResourcesEntityList(mActorSiteRoleRepository.GetActorSiteRoles());
					if (isCached)
					{
						CacheHandler.Store<List<Entities.ActorSiteRole>>(CACHEKEY_ACTORSITEROLES, actorsSiteRoles, ConfigurationManager.CacheExpirations.Warehouse.Actors);
					}
					return actorsSiteRoles;
				}
			}
		}


		#endregion

		#region Constructor logic

		private ActorSiteRoleFactory()
		{
		}

		#endregion

		#region Repository handler methods

		#region Create

		public static Entities.ActorSiteRole CreateActorSiteRole(Int32 actorId, Int32 siteId, Int32 roleId)
		{
			Resources.Entities.ActorSiteRole actorSiteRole = new Resources.Entities.ActorSiteRole();

			actorSiteRole.ActorId = actorId;
			actorSiteRole.RoleId = roleId;
			actorSiteRole.SiteId = siteId;

			mActorSiteRoleRepository.Add(actorSiteRole);

			return ConvertResourcesEntity(actorSiteRole);
		}

		#endregion

		#region Read

		public static List<Entities.Role> ReadRolesByActorIdAndSiteId(int actorId, int siteId)
		{
			List<Entities.Role> rList = new List<Entities.Role>();
			foreach (Entities.ActorSiteRole asr in mActorSiteRoleListByActorId[actorId])
			{
				if (asr.SiteId == siteId)
				{
					Entities.Role role = RoleFactory.ReadRoleById(asr.RoleId);
					rList.Add(role);
				}
			}
			return rList;
		}

		public static List<Entities.Site> ReadSitesByActorIdAndRoleId(int actorId, int roleId)
		{
			List<Entities.Site> sList = new List<Entities.Site>();
			foreach (Entities.ActorSiteRole asr in mActorSiteRoleListByActorId[actorId])
			{
				if (asr.RoleId == roleId)
				{
					Entities.Site site = SiteFactory.ReadSiteById(asr.SiteId);
					sList.Add(site);
				}
			}
			return sList;
		}

		public static List<Entities.Actor> ReadActorsBySiteIdAndRoleId(int siteId, int roleId)
		{
			List<Entities.Actor> aList = new List<Entities.Actor>();
			foreach (Entities.ActorSiteRole asr in mActorSiteRoleListBySiteId[siteId])
			{
				if (asr.RoleId == roleId)
				{
					Entities.Actor actor = ActorFactory.ReadActorById(asr.ActorId);
					aList.Add(actor);
				}
			}
			return aList;
		}

		public static Dictionary<int, List<Entities.Actor>> ReadActorsBySiteIdKeyedOnRoleId(int siteId)
		{
			Dictionary<int, List<Entities.Actor>> actorDict = new Dictionary<int, List<Entities.Actor>>();
			foreach (Entities.ActorSiteRole asr in mActorSiteRoleListBySiteId[siteId])
			{
				if (!actorDict.ContainsKey(asr.RoleId))
				{
					actorDict.Add(asr.RoleId, new List<Entities.Actor>());
				}
				Entities.Actor actor = ActorFactory.ReadActorById(asr.ActorId);
				actorDict[asr.RoleId].Add(actor);
			}

			return actorDict;
		}

		public static Dictionary<int, List<Entities.Role>> ReadRolesByActorIdKeyedOnSiteId(int actorId)
		{
			Dictionary<int, List<Entities.Role>> rDict = new Dictionary<int, List<Entities.Role>>();
			foreach (Resources.Entities.ActorSiteRole asr in mActorSiteRoleListByActorId[actorId])
			{
				if (!rDict.ContainsKey(asr.SiteId))
				{
					rDict.Add(asr.SiteId, new List<Entities.Role>());
				}
				Entities.Role role = RoleFactory.ReadRoleById(asr.RoleId);
				rDict[asr.SiteId].Add(role);
			}

			return rDict;
		}

		public static Dictionary<int, List<Entities.Site>> ReadSitesByRoleIdKeyedOnActorId(int roleId)
		{
			Dictionary<int, List<Entities.Site>> sDict = new Dictionary<int, List<Entities.Site>>();
			foreach (Resources.Entities.ActorSiteRole asr in mActorSiteRoleListByRoleId[roleId])
			{
				if (!sDict.ContainsKey(asr.ActorId))
				{
					sDict.Add(asr.ActorId, new List<Entities.Site>());
				}
				Entities.Site site = SiteFactory.ReadSiteById(asr.SiteId);
				sDict[asr.ActorId].Add(site);
			}

			return sDict;
		}

		#endregion

		#region Update

		public static void UpdateActorSiteRole(Entities.ActorSiteRole actorSiteRole)
		{
			mActorSiteRoleRepository.Update(actorSiteRole);
		}

		#endregion

		#region Delete

		public static void DeleteActorSiteRole(Entities.ActorSiteRole actorSiteRole)
		{
			DeleteActorSiteRole(actorSiteRole);
		}

		public static void DeleteActorSiteRole(int actorId, int siteId, int roleId)
		{
			mActorSiteRoleRepository.Remove(actorId, siteId, roleId);
		}

		public static void DeleteActorSiteRole(Entities.Actor actor, Entities.Site site, Entities.Role role)
		{
			DeleteActorSiteRole(actor.Id, site.Id, role.Id);
		}

		#endregion

		#endregion

		#region Internal converter methods

		internal static List<Entities.ActorSiteRole> ConvertResourcesEntityList(List<Resources.Entities.ActorSiteRole> list)
		{
			return list.ConvertAll<Entities.ActorSiteRole>(new Converter<Resources.Entities.ActorSiteRole, Entities.ActorSiteRole>(ConvertResourcesEntity));
		}

		internal static Entities.ActorSiteRole ConvertResourcesEntity(Resources.Entities.ActorSiteRole actorSiteRole)
		{
			return new Entities.ActorSiteRole(actorSiteRole);
		}

		#endregion

	}
}
